package problems;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import representation.Memory;

import individual.Pindividual;

public class TSP implements Problem{
	
	private int points[][];
	private boolean used[];
	private static final int solutionOffset = 300;
	
	public TSP()
	{
		init();
	}
	
	public void init()
	{
		try {
			
			BufferedReader reader = new BufferedReader(new FileReader("500cycle.in"));
			
			String line = reader.readLine();			
			int length = Integer.parseInt(line);
			points = new int[length][];
			used = new boolean[length];
			
			for(int i = 0; i < length; i++ )
			{
				points[i] = new int[2];				
				line = reader.readLine();
				
				points[i][0] = Integer.parseInt(line.split(" ")[0]);
				points[i][1] = Integer.parseInt(line.split(" ")[1]);				
			}			
			
			reader.close();
		}
		catch(FileNotFoundException e)
		{
			System.out.println("File not found");
			System.exit(1);
		}
		catch(IOException e) {
			System.out.println("Invalid format");
			System.exit(1);
		}
		catch(ArrayIndexOutOfBoundsException e)
		{
			System.out.println("Invalid format");
			System.exit(1);
		}
		
	}
	
	private double D(double dx, double dy)
	{
		return Math.sqrt(dx*dx + dy*dy);
	}
	
	public void eval(Pindividual p)
	{
		int n1 = p.codeMemory.getValue(solutionOffset+points.length-1);
		int offset1 = n1 % points.length;
		offset1 = offset1 >= 0 ? offset1 : offset1 + points.length;
		int x1 = points[offset1][0];
		int y1 = points[offset1][1];
		int n2 = p.codeMemory.getValue(solutionOffset);
		int offset2 = n2%points.length;
		offset2 = offset2 >= 0 ? offset2 : offset2 + points.length;
		int x2 = points[offset2][1];
		int y2 = points[offset2][1];		
		double dist = D(x2-x1, y2-y1);
		
		for(int i = 0; i < points.length;i++)
		{
			used[i] = false;
		}
		
		used[offset1] = true;
		used[offset2] = true;
						
		for(int i = 1; i < points.length-2; i++)
		{	
			n1 = n2;
			n2 = p.codeMemory.getValue(solutionOffset+i);			
			offset1 = n1 % points.length;
			offset1 = offset1 >= 0 ? offset1 : offset1 + points.length;
			offset2 = n2 % points.length;
			offset2 = offset2 >= 0 ? offset2 : offset2 + points.length;
			
			x1 = points[offset1][0];
			y1 = points[offset1][1];
			x2 = points[offset2][0];
			y2 = points[offset2][1];
			
			used[offset1] = true;
			used[offset2] = true;
			
			dist += D(x2-x1,y2-y1);
		}
		
		double score = 0;
		
		for(int i = 0; i< points.length; i++)
		{
			if(used[i])
				score += 1;
		}
		
		p.score = score;
		//p.score = score - dist; // target for actual TSP
		//p.score = p.score >0 ? p.score : 0;
	}
}
